/** 
 * @Description: 雷达创建类
 * @Author: 程前
 * @Date: 2025-01-21 16:09:33
 * @LastEditors: 程前
 * @LastEditTime: 2025-02-17 10:49:59
 */
import { Viewer, Cartesian3, Color, CallbackProperty, Matrix4, Transforms, Math as CesiumMath, DistanceDisplayCondition, Cartographic } from 'cesium';

interface TrackMatteOptions {
    viewer: Viewer;
    id: string;
    range: number;
    position: [number, number];
}

export class TrackMatte {
    private viewer: Viewer;
    public id: string;
    private range: number;
    private longitude: number;
    private latitude: number;
    private position: Cartesian3;
    private heading: number;
    private positionArr: number[];

    constructor(val: TrackMatteOptions) {
        this.viewer = val.viewer;
        this.id = val.id;
        this.range = val.range;
        this.longitude = val.position[0];
        this.latitude = val.position[1];
        this.position = Cartesian3.fromDegrees(
            val.position[0],
            val.position[1],
        );
        this.heading = 0;
        this.positionArr = this.calcPoints(
            val.position[0],
            val.position[1],
            val.range,
            0
        );
        this.addEntities();
    }

    private addEntities(): void {
        this.viewer.entities.add({
            id: this.id,
            position: this.position,
            wall: {
                positions: new CallbackProperty(() => {
                    return Cartesian3.fromDegreesArrayHeights(this.positionArr);
                }, false),
                material: Color.RED.withAlpha(0.2),
            },
            ellipsoid: {
                radii: new Cartesian3(
                    this.range,
                    this.range,
                    this.range
                ),
                maximumCone: CesiumMath.toRadians(90),
                material: Color.RED.withAlpha(0.2),
                outline: true,
                outlineColor: Color.YELLOW.withAlpha(0.7),
                outlineWidth: 1,
            },
        });
        this.addPostRender();
    }

    /**
     * 雷达动态效果
     */
    private addPostRender(): void {
        this.viewer.clock.onTick.addEventListener(() => {
            this.heading += 10.0; //可调节转动速度
            this.positionArr = this.calcPoints(
                this.longitude,
                this.latitude,
                this.range,
                this.heading
            );
        });
    }

    /**
     * 计算角度变化后的扫描线坐标
     * 大体逻辑:根据中心点建立局部东北天坐标系 
     * 然后根据雷达半径以及当前扫描线角度转换为弧度计算出扫描线终点坐标
     */
    private calcPoints(x1: number, y1: number, radius: number, heading: number): number[] {
        const m = Transforms.eastNorthUpToFixedFrame(
            Cartesian3.fromDegrees(x1, y1)
        );
        const rx = radius * Math.cos((heading * Math.PI) / 180.0);
        const ry = radius * Math.sin((heading * Math.PI) / 180.0);
        const translation = Cartesian3.fromElements(rx, ry, 0);
        const d = Matrix4.multiplyByPoint(
            m,
            translation,
            new Cartesian3()
        );
        const cartographic = Cartographic.fromCartesian(d);
        const x2 = CesiumMath.toDegrees(cartographic.longitude);
        const y2 = CesiumMath.toDegrees(cartographic.latitude);
        return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90);
    }

    /**
     * 根据中心点及终点坐标生成扫描线路径——即动态弧度墙体坐标组
     */
    private computeCirclularFlight(x1: number, y1: number, x2: number, y2: number, fx: number, angle: number): number[] {
        const positionArr: number[] = [];
        positionArr.push(x1, y1, 0);
        for (let i = fx; i <= fx + angle; i++) {
            const h = this.range * Math.sin((i * Math.PI) / 180.0);
            const r = Math.cos((i * Math.PI) / 180.0);
            const x = (x2 - x1) * r + x1;
            const y = (y2 - y1) * r + y1;
            positionArr.push(x, y, h);
        }
        return positionArr;
    }
} 